package com.googlecode.javatools.domain.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.googlecode.javatools.classparser.types.ClassInfo;
import com.googlecode.javatools.classparser.types.FieldInfo;
import com.googlecode.javatools.classparser.types.FileHeaderInfo;
import com.googlecode.javatools.domain.Field;
import com.googlecode.javatools.domain.JavaClass;
import com.googlecode.javatools.domain.Method;

public class ParsedJavaClass implements JavaClass
{
	private final FileHeaderInfo fileHeaderInfo;
	private final ClassInfo classInfo;
	private final Collection<FieldInfo> fieldInfos;
	private final Collection<FieldInfo> methodInfos;

	public ParsedJavaClass(final FileHeaderInfo fileHeaderInfo, final ClassInfo classInfo,
			final Collection<FieldInfo> fieldInfos, final Collection<FieldInfo> methodInfos)
	{
		this.fileHeaderInfo = fileHeaderInfo;
		this.classInfo = classInfo;
		this.fieldInfos = fieldInfos;
		this.methodInfos = methodInfos;
	}

	public boolean isValid()
	{
		return 0xCAFEBABE == fileHeaderInfo.magic();
	}

	public String version()
	{
		return fileHeaderInfo.majorVersion() + "." + fileHeaderInfo.minorVersion();
	}

	public String className()
	{
		return classInfo.className();
	}

	public String fullyQualifiedName()
	{
		return classInfo.fullyQualifiedClassName();
	}

	public String fullyQualifiedSuperClassName()
	{
		return classInfo.fullyQualifiedSuperClassName();
	}

	public String packageName()
	{
		return classInfo.packageName();
	}

	public boolean isAbstract()
	{
		return classInfo.isAbstract();
	}

	public boolean isInterface()
	{
		return classInfo.isInterface();
	}

	public boolean isPublic()
	{
		return classInfo.isPublic();
	}

	public List<Field> fields()
	{
		final List<Field> fields = new ArrayList<Field>();
		for (final FieldInfo fieldInfo : fieldInfos)
		{
			fields.add(fieldInfoToField(fieldInfo));
		}
		return fields;
	}

	public List<Method> methods()
	{
		final List<Method> fields = new ArrayList<Method>();
		for (final FieldInfo methodInfo : methodInfos)
		{
			fields.add(fieldInfoToMethod(methodInfo));
		}
		return fields;
	}

	public List<String> imports()
	{
		final List<String> imports = new ArrayList<String>();

		final Collection<String> associatedTypes = new ArrayList<String>();
		associatedTypes.add(fullyQualifiedSuperClassName());
		associatedTypes.addAll(classInfo.interfaces());
		associatedTypes.addAll(classInfo.interfaces());

		for (final FieldInfo fieldInfo : fieldInfos)
		{
			associatedTypes.addAll(fieldInfo.types());
		}

		for (final FieldInfo methodInfo : methodInfos)
		{
			associatedTypes.addAll(methodInfo.types());
		}

		for (final String associatedType : associatedTypes)
		{
			if (!packageOf(associatedType).equals(packageName()))
			{
				imports.add(associatedType);
			}
		}

		return imports;
	}

	private Field fieldInfoToField(final FieldInfo fieldInfo)
	{
		return new FieldImpl(fieldInfo);
	}

	private Method fieldInfoToMethod(final FieldInfo methodInfo)
	{
		return new MethodImpl();
	}

	private static String packageOf(final String fullyQualifiedClassName)
	{
		return fullyQualifiedClassName.substring(0, fullyQualifiedClassName.lastIndexOf("."));
	}

}
